package com.nctu.dm.fpgrowth;

import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;
public class FPT {
	public HeadTable HT;
	public Vector<TransactionTable> TransactionTableForEachItem;
	private Node root;	
	public class HeadTable{
		Map<String, HeadTableValue> Table;
		public void printhead()
		{
			for(Map.Entry<String,FPT.HeadTable.HeadTableValue> e:HT.Table.entrySet()){
				System.out.print("~~~~~~~~~~~~~~~~~~~~~~~~~~"+e.getKey()+":"+"("+e.getValue().getfre()+")~~~~~~~~~~~~~~~~~~~~~~~~~\n");
			}
		}
		public class HeadTableValue{
			int frequency = 0;
			Vector<Node> head = null;
			public HeadTableValue(int frequency,Node head){
				this.frequency = frequency;
				this.head = new Vector<Node>();
				this.head.add(head);
			}
			public HeadTableValue(){
				this.frequency = 0;
				this.head = new Vector<Node>();
			}
			public void addhead(Node head){
				this.head.add(head);
			}
			public int getfre()
			{
				return frequency;
			}
		}		
		public HeadTable(){
			Table = new TreeMap<String, HeadTableValue>(new Mycompare());
		}
		
		public void addValue(String key,int frequency){	
			if(Table.containsKey(key)){
				Table.get(key).frequency += frequency;
			}else{
				System.out.print("You must use put method first\n");
			}
			
		}
		private Vector<Node> __GetHeader(String s){
			//Vector<Node> temp = HT.Table.get(s).head;
			return HT.Table.get(s).head ;
			//return temp;
		}
		
		public void put(String key,int frequency,Node head){
			if(!Table.containsKey(key)){
				HeadTableValue HTV = new HeadTableValue(frequency,head);
				Table.put(key, HTV);
			}else{
				Table.get(key).addhead(head);
				Table.get(key).frequency+=frequency;
			}
		}
	}
	private class Node{
		private Vector<Node> downlink;
		private Node uplink;
		private class Value{
			private String item;
			private int frequency;
			private Value(){
				item = "";
				frequency = 0;
			}
			private Value(String i,int f)
			{
				this.item = i;
				this.frequency = f;
			}
			
		}
		Value value;
		private Node(){
			value = new Value();
			value.item = "";
			value.frequency = 0;
			downlink = new Vector<Node>();
			uplink = null;
		}
		private Node(String i, int f){
			value = new Value();
			value.item = i;
			value.frequency = f;
			downlink = new Vector<Node>();
			uplink = null;		
		}
		private void __SetValue(String i,int f){
			value.item = i;
			value.frequency = f;	
		}
		private int printvalue()
		{
			return value.frequency;
		}
		private void __addValue(int f){
			value.frequency += f;
		}
	}
	
	
	
	public FPT(){
		root = new Node("root",0);
		HT= new HeadTable();
	}
	public void addT(TransactionValuePair data)
	{
		__addChild(root,data);
		
	}
	private void __addChild(Node root,TransactionValuePair Transac)
	{
		int finish = 0;
		Node current = root;
		if(Common.Debug) System.out.printf("start from %s\n",root.value.item);
		for(String s:Transac.trans){
			System.out.print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
			HT.printhead();
			System.out.print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
			for(Node d:current.downlink){
				if(Common.Debug) System.out.printf("current's downlink is %s\n",d.value.item);
				if (s.compareTo(d.value.item)==0)
				{
					if(Common.Debug) System.out.printf("add value for %s\n",s);
					System.out.print("\n\n\nvalue:"+d.printvalue()+"\nTransac.count:"+Transac.count+"\n\n\n");
					//d.__addValue(Transac.count);
					//HT.addValue(s, d.value.frequency);
					HT.addValue(s, Transac.count);
					//HT.addValue(s, d.value.frequency);
					d.__addValue(Transac.count);
					current = d;
					finish = 1;
					break;
				}
			}
			if(finish == 0){
				Node newnode = new Node(s,Transac.count);
				//let head table to point this node
				if(Common.Debug) System.out.printf("create new node for %s\n",s);
				HT.put(s, Transac.count, newnode);
				current.downlink.add(newnode);
				newnode.uplink = current;
				current = newnode;
			}else{
				finish = 0;
			}
		}
	}
	public Vector<TransactionValuePair> __GetPatterns(String base)
	{
		if(Common.Debug){
			System.out.printf("Get Pattern for key %s\n",base);
		}		
		Vector<Node> header = HT.__GetHeader(base);
		Vector<TransactionValuePair> patterns = new Vector<TransactionValuePair>();
		Node current;
		int firstLoop = 1;
		for(Node n:header){
			firstLoop = 1;
			current = n;
			TransactionValuePair tvp = new TransactionValuePair();
			Vector<String> trans = new Vector<String>(); 
			while(current.uplink.value.item!="root"){
				if(Common.Debug){
					System.out.printf("%s\n",current.uplink.value.item);
				}
				if(firstLoop == 1){
					tvp.count = n.value.frequency;
					firstLoop = 0;
				}
				trans.add(0, current.uplink.value.item);
				current = current.uplink;
			}
			if(trans.size()!=0){
				tvp.trans = trans;
				patterns.add(tvp);
				if(Common.Debug){
					System.out.printf("%s\n",tvp.trans.toString());
				}				
			}
			trans = null;
		}
		return patterns;
	}
	
	public void DeallocateSources()
	{
		//delete HT
		HT = null;
		//Delete Tree
		root = null;
	}
	
}
